package eu.jk.data.dbcp;

import java.sql.Connection;
import java.sql.Statement;
import java.util.LinkedList;
import java.util.Queue;


public class Pool{
	
	private Queue<Wraper> pool = new LinkedList<Wraper>();
	
	private PoolConfig config = null;

	private Machine machine = null;
	
	public Pool(PoolConfig config) {
		this.config = config;
		machine = new Machine(this);
		machine.start();
		machine.runAmount(5);
	}

	public Connection getConnection() throws GetConnectionFailException {
		Connection conn = null;
		int tryCount=config.getClientTryCount();
		int count=0;
		while (true) {
			if(!(tryCount <= 0 || count < tryCount)){
				throw new GetConnectionFailException("Wait too long when try to get connection");
			}
			count++;
			synchronized (pool) {
				if(pool.size()>0)
					conn = pool.poll().getConnection();
				if(pool.size()<config.getLowCase()){
					machine.runAmount(config.getIncrease());
				}
			}
			if(this.validate(conn))
				return conn;
			synchronized(this){
				try {
					wait(200);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public void putConnection(Connection conn){
		synchronized(pool){
			pool.add(new Wraper(conn));
		}
	}
	/**
	 * 验证连接有效性
	 * 
	 * @param conn
	 * @return 连接是否有效
	 */
	private boolean validate(Connection conn) {
		if (conn == null)
			return false;
		try {
			Statement stmt = conn.createStatement();
			if (!stmt.execute("select 1"))
				return false;
			stmt.close();
		} catch (Exception e) {
			return false;
		}
		return true;
	}

	public PoolConfig getConfig() {
		return config;
	}
}
